package com.slipper.codeless.resolve.query;

import com.slipper.codeless.resolve.SymbolUtil;
import com.slipper.constants.Constants;
import com.slipper.exception.CommonException;
import com.slipper.system.codeless.bo.*;
import com.slipper.system.codeless.service.DataFieldService;
import com.slipper.system.codeless.service.DataModelService;
import com.slipper.system.codeless.service.DataTableFieldService;
import com.slipper.system.codeless.service.ViewService;
import com.slipper.system.role.bo.RoleBO;
import com.slipper.util.DateUtil;
import com.slipper.util.Tool;
import org.springframework.stereotype.Component;

import jakarta.annotation.Resource;

import java.text.ParseException;
import java.util.*;

@Component
public class QueryResolver {
    @Resource
    private DataModelService dataModelService;
    @Resource
    private DataFieldService dataFieldService;
    @Resource
    private DataTableFieldService dataTableFieldService;
    @Resource
    private ViewService viewService;

    public Query resolve(DataModelBO dataModel, Map<String, Object> data) {
        return resolve(null, dataModel, null, null, null, data);
    }

    public Query resolve(DataModelBO dataModel, Map<String, Object> data, Map<String, String> orderMap) {
        Query query = resolve(null, dataModel, null, null, null, data);
        if (orderMap != null && !orderMap.isEmpty()) {
            int i=0;
            for (Map.Entry<String, String> entry : orderMap.entrySet()) {
                query.addSortField(entry.getKey(), entry.getValue(), ++i);
            }
        }
        return query;
    }

    @SuppressWarnings("unchecked")
    public Query resolve(
            PageCompBO pageComp,
            DataModelBO dataModel,
            List<PageCompFilterBO> filterList,
            List<PrivilegeBO> privilegeList,
            List<DataTableOrdinalBO> ordinalList,
            Map<String, Object> data) {
        if (dataModel == null) throw new CommonException("数据集不存在！");

        List<List<Object>> inputParamList = new ArrayList<>();
        if (data.containsKey("inputParamList") && data.get("inputParamList") != null) {
            inputParamList = (List<List<Object>>) data.get("inputParamList");
        }

        Query query = new Query();
        if (Constants.DataModel.TYPE_TABLE.equals(dataModel.getType())) {
            query.setTableName(dataModel.getCode());
            if (Tool.isBlank(data.get("id")) && dataModel.getCode().equals("sys_employee")) {
                List<Condition> conditionList = new ArrayList<>();
                conditionList.add(new Condition("id", "字符", Condition.MATCH_MODE_NOT_ADMIN, "-"));
                query.addCondition(conditionList);
            }
        } else {
            ViewBO view = viewService.queryBy(dataModel.getSourceId());
            if (ViewBO.SOURCE_BUILTIN.equals(view.getSource())) {
                query.setTableName(view.getCode());
            } else {
                query.setLocal(false);
                query.setDatasourceId(view.getDatasourceId());
                query.setTableName(view.getSqlText());
            }
        }

        // 树形过滤，传入参数以id传值
        buildTreeFilter(query, pageComp, dataModel, data);

        for (DataFieldBO field : dataModel.getFieldList()) {
            if (!DataFieldBO.FIELD_TYPE_DERIVE.equals(field.getFieldType())) {
                buildCommonField(query, dataModel, field, inputParamList, data);
            }
        }

        // 高级查询
        buildAdvanceQuery(
                String.valueOf(data.get("advanceQuery")),
                String.valueOf(data.get("advanceQueryTableId")),
                query,
                dataModel.getFieldList());

        // 数据过滤条件
        buildDataFilter(query, dataModel, data);

        // 页面过滤条件
        buildPageFilter(query, dataModel, filterList, data);

        // 权限过滤
        buildPrivilegeFilter(query, dataModel, privilegeList);

        // 配置过滤
        buildConfigFilter(query, dataModel, data);

        // 数据排序
        buildDataOrder(query, data);

        // 配置排序
        buildConfigOrder(query, ordinalList);

        // 默认排序
        buildDefaultOrder(query, dataModel.getFieldList());

        return query;
    }

    private void buildDeriveField(Query query, DataFieldBO field, Map<String, Object> data) {
        DataFieldBO sourceDataField = dataFieldService.queryBy(field.getSourceFieldId());
        QueryField queryField = new QueryField();
        queryField.setOriginName(field.getFieldName());
        queryField.setTargetName(field.getFieldName() + "_name");
//        query.addQueryField(queryField);
        buildByDataField(
                "as_" + field.getNativeFieldId(),
                query,
                queryField,
                sourceDataField,
                new ArrayList<>(),
                data);
    }


    private void buildCommonField(
            Query query,
            DataModelBO dataModel,
            DataFieldBO field,
            List<List<Object>> inputParamList,
            Map<String, Object> data) {
        QueryField queryField = new QueryField();
        queryField.setOriginName(field.getFieldName());
        queryField.setTargetName(field.getFieldName() + "_name");

        if (DataFieldBO.FIELD_TYPE_RELATION.equals(field.getFieldType())
                && DataFieldBO.RELEVANCE_TYPE_EMP.equals(field.getRelevanceType())) {
            dataModel.getFieldList().stream()
                    .filter(item -> field.getId().equals(item.getNativeFieldId()))
                    .findFirst()
                    .ifPresent(item -> queryField.setConcat("@", item.getFieldName(), field.getFieldName()));
        }
        query.addQueryField(queryField);

        // 查询过滤
        List<Condition> conditionList = new ArrayList<>();
        if (Tool.isNotBlank(data.get(field.getFieldName()))) {
            conditionList.add(new Condition(
                    field.getFieldName(),
                    field.getFieldType(),
                    Constants.YES.equals(field.getPrimaryKey()) || DataFieldBO.FIELD_TYPE_RELATION.equals(field.getFieldType())
                            ? Condition.MATCH_MODE_EQU : Condition.MATCH_MODE_LIKE,
                    parseValue(field, data.get(field.getFieldName()), null)));
        }
        query.addCondition(conditionList);

        // 入参过滤
        List<Condition> inputConditionList = new ArrayList<>();
        inputParamList.forEach(inputParam -> {
            if (inputParam.size() < 2) return;

            if (Tool.isNotBlank(inputParam.get(0))
                    && Tool.isNotBlank(inputParam.get(1))
                    && inputParam.get(0).equals(field.getFieldName())) {
                inputConditionList.add(new Condition(
                        field.getFieldName(),
                        field.getFieldType(),
                        inputParam.size() >= 3 && Tool.isNotBlank(inputParam.get(1))
                                ? String.valueOf(inputParam.get(1)) : Condition.MATCH_MODE_EQU,
                        parseValue(field, inputParam.size() >= 3 ? inputParam.get(2) : inputParam.get(1), null)));
            }
        });
        query.addCondition(inputConditionList);

        buildByDataField(null, query, queryField, field, dataModel.getFieldList(), data);
    }

    private void buildAdvanceQuery(String advanceQuery, String tableId, Query query, List<DataFieldBO> fieldList) {
        if (Tool.isBlank(advanceQuery) || Tool.isBlank(tableId)) return;

        List<DataTableFieldBO> tableFieldList = dataTableFieldService.queryByTableId(tableId);
        String[] ands = advanceQuery.split("&");
        for (String and : ands) {
            if (Tool.isBlank(and.trim())) continue;
            String[] ors = and.split("\\|");
            List<Condition> conditionList = buildOrCondition(ors, tableFieldList, fieldList);
            if (!conditionList.isEmpty()) {
                query.addOrCondition(conditionList);
            }
        }
    }

    private List<Condition> buildOrCondition(
            String[] params,
            List<DataTableFieldBO> tableFieldList,
            List<DataFieldBO> fieldList) {
        List<Condition> conditionList = new ArrayList<>();
        for (String param : params) {
            if (Tool.isBlank(param.trim())) continue;
            tableFieldList.forEach(tableField ->
                fieldList.stream()
                        .filter(field -> field.getId().equals(tableField.getFieldId()))
                        .findFirst()
                        .ifPresent(field -> {
                            if (DataFieldBO.FIELD_TYPE_VARCHAR.equals(field.getFieldType())
                                    || DataFieldBO.FIELD_TYPE_TEXT.equals(field.getFieldType())) {
                                conditionList.add(new Condition(
                                        false,
                                        "or",
                                        field.getFieldName(),
                                        field.getFieldType(),
                                        Condition.MATCH_MODE_LIKE,
                                        param));
                            } else if (DataFieldBO.FIELD_TYPE_RELATION.equals(field.getFieldType())
                                    || DataFieldBO.FIELD_TYPE_DERIVE.equals(field.getFieldType())) {
                                conditionList.add(new Condition(
                                        true,
                                        "or",
                                        field.getFieldName() + "_name",
                                        field.getFieldType(),
                                        Condition.MATCH_MODE_LIKE,
                                        param));
                            }
                        })
            );
        }
        return conditionList;
    }

    private void buildTreeFilter(Query query, PageCompBO pageComp, DataModelBO dataModel, Map<String, Object> data) {
        if (pageComp == null || Tool.isBlank(pageComp.getFilterFieldId())) return;

        if(PageCompBO.TREE_MAPPING_TYPE_ONE.equals(pageComp.getTreeMappingType())) {
            if (Tool.isBlank(data.get(pageComp.getFilterFieldId()))) return;

            dataModel.getFieldList().stream()
                    .filter(dataField -> dataField.getId().equals(pageComp.getFilterFieldId()))
                    .findFirst()
                    .ifPresent(dataField -> {
                        List<Condition> conditionList = new ArrayList<>();
                        if (Constants.YES.equals(pageComp.getRecursiveQuery())) {
                            DataModelBO treeModel = dataModelService.queryBy(pageComp.getTreeDataModelId());
                            conditionList.add(new Condition(
                                    dataField.getFieldName(),
                                    dataField.getFieldType(),
                                    treeModel.getCode(),
                                    pageComp.getTreeNodeFieldName(),
                                    pageComp.getTreeParentFieldName(),
                                    Condition.MATCH_MODE_RECURSIVE,
                                    parseValue(dataField, data.get(pageComp.getFilterFieldId()), null)));
                        } else {
                            conditionList.add(new Condition(
                                    dataField.getFieldName(),
                                    dataField.getFieldType(),
                                    Condition.MATCH_MODE_EQU,
                                    parseValue(dataField, data.get(pageComp.getFilterFieldId()), null)));
                        }
                        query.addCondition(conditionList);
                    });
        } else if (PageCompBO.TREE_MAPPING_TYPE_MULTI.equals(pageComp.getTreeMappingType())) {
            if (Tool.isBlank(data.get(pageComp.getMiddleInputFieldId()))) return;

            DataModelBO middleDataModel = dataModelService.queryBy(pageComp.getMiddleModelId());
            LeftJoinQuery leftJoinQuery = new LeftJoinQuery();

            dataModel.getFieldList().stream()
                    .filter(dataField -> dataField.getId().equals(pageComp.getFilterFieldId()))
                    .findFirst()
                    .ifPresent(dataField -> {
                        leftJoinQuery.setAlias("as_" + dataField.getId());
                        leftJoinQuery.setSourceFieldName(dataField.getFieldName());
                    });

            leftJoinQuery.setTargetId(middleDataModel.getId());
            leftJoinQuery.setTargetTableName(middleDataModel.getCode());

            List<DataFieldBO> dataFieldList = dataFieldService.queryListBy(middleDataModel.getId());
            dataFieldList.stream()
                    .filter(dataField -> dataField.getId().equals(pageComp.getMiddleOutputFieldId()))
                    .findFirst()
                    .ifPresent(dataFieldBO -> leftJoinQuery.setTargetPrimaryKey(dataFieldBO.getFieldName()));

            dataFieldList.stream()
                    .filter(dataField -> dataField.getId().equals(pageComp.getMiddleInputFieldId()))
                    .findFirst()
                    .ifPresent(dataField -> leftJoinQuery.addCondition(
                            dataField.getFieldName(),
                            dataField.getFieldType(),
                            Condition.MATCH_MODE_EQU,
                            data.get(pageComp.getMiddleInputFieldId())));

            query.addLeftJoinQuery(leftJoinQuery);
        }
    }

    private void buildByDataField(
            String sourceAlias,
            Query query,
            QueryField queryField,
            DataFieldBO dataField,
            List<DataFieldBO> dataFieldList,
            Map<String, Object> data) {
        if (DataFieldBO.FIELD_TYPE_RELATION.equals(dataField.getFieldType())) {
            if (Tool.isNotBlank(dataField.getRelevanceType()) && dataField.getRelevanceType().startsWith("字典")) {
                query.addLeftJoinQuery(getDictLeftJoinQuery(sourceAlias, queryField, dataField, data));
            } else if (DataFieldBO.RELEVANCE_TYPE_AREA.equals(dataField.getRelevanceType())
                    || DataFieldBO.RELEVANCE_TYPE_UNIT.equals(dataField.getRelevanceType())
                    || DataFieldBO.RELEVANCE_TYPE_ENP.equals(dataField.getRelevanceType())
                    || DataFieldBO.RELEVANCE_TYPE_DEPT.equals(dataField.getRelevanceType())) {
                query.addLeftJoinQuery(getOrganizationLeftJoinQuery(sourceAlias, queryField, dataField, data));
            } else if (DataFieldBO.RELEVANCE_TYPE_EMP.equals(dataField.getRelevanceType())) {
                query.addLeftJoinQuery(getEmployeeLeftJoinQuery(sourceAlias, queryField, dataField, data));
            } else if (!dataField.getRelevanceList().isEmpty()) {
                DataFieldRelevanceBO relevance = dataField.getRelevanceList().getLast();
                if (relevance == null) return;

                DataModelBO relevanceDataModel = dataModelService.queryBy(relevance.getDataModelId());
                LeftJoinQuery leftJoinQuery = new LeftJoinQuery();
                leftJoinQuery.setAlias("as_" + dataField.getId());
                leftJoinQuery.setSourceFieldName(dataField.getFieldName());
                leftJoinQuery.setTargetId(relevanceDataModel.getId());

                if (Constants.DataModel.TYPE_TABLE.equals(relevanceDataModel.getType())) {
                    leftJoinQuery.setTargetTableName(relevanceDataModel.getCode());
                } else if (Constants.DataModel.TYPE_VIEW.equals(relevanceDataModel.getType())) {
                    leftJoinQuery.setTargetTableName(relevanceDataModel.getCode());
                    ViewBO view = viewService.queryBy(relevanceDataModel.getSourceId());
                    leftJoinQuery.setTargetTableName(view.getCode());
                }

                List<DataFieldBO> relevanceFieldList = dataFieldService.queryListBy(relevance.getDataModelId());
                DataFieldBO dataFieldBO = relevanceFieldList.stream()
                        .filter(item -> relevance.getNodeFieldId().equals(item.getId()))
                        .findFirst().orElse(null);
                DataFieldBO dataFieldShow = relevanceFieldList.stream()
                        .filter(item -> item.getId().equals(relevance.getShowFieldId()))
                        .findFirst().orElse(null);
                leftJoinQuery.setTargetPrimaryKey(dataFieldBO == null ? "id" : dataFieldBO.getFieldName());
                if (dataFieldShow != null) {
                    leftJoinQuery.addFieldMapping(dataFieldShow.getFieldName(), dataField.getFieldName() + "_name");
                    if (Tool.isNotBlank(data.get("sortField"))
                            && (dataField.getFieldName() + "_name").equals(data.get("sortField"))) {
                        leftJoinQuery.setSortField(dataFieldShow.getFieldName());
                        leftJoinQuery.setSortType((String) data.get("sortType"));
                    }
                }

                query.addLeftJoinQuery(leftJoinQuery);
                dataFieldList.stream()
                        .filter(field -> dataField.getId().equals(field.getNativeFieldId()))
                        .forEach(field -> {
                            DataFieldBO sourceDataField = dataFieldService.queryBy(field.getSourceFieldId());
                            if (DataFieldBO.FIELD_TYPE_RELATION.equals(sourceDataField.getFieldType())) {
                                QueryField sourceQueryField = new QueryField();
                                sourceQueryField.setOriginName(field.getFieldName());
                                sourceQueryField.setTargetName(field.getFieldName());
                                buildByDataField(
                                        "as_" + field.getNativeFieldId(),
                                        query,
                                        sourceQueryField,
                                        sourceDataField,
                                        new ArrayList<>(),
                                        data);
                            } else {
                                relevanceFieldList.stream()
                                        .filter(item -> item.getId().equals(field.getSourceFieldId()))
                                        .findFirst()
                                        .ifPresent(item -> {
                                            leftJoinQuery.addFieldMapping(item.getFieldName(), field.getFieldName());
                                            if (Tool.isNotBlank(data.get("sortField"))
                                                    && field.getFieldName().equals(data.get("sortField"))) {
                                                leftJoinQuery.setSortField(item.getFieldName());
                                                leftJoinQuery.setSortType((String) data.get("sortType"));
                                            }
                                        });
                            }
                        });
            }
        } else if (DataFieldBO.FIELD_TYPE_DERIVE.equals(dataField.getFieldType())) {
            buildDeriveField(query, dataField, data);
        } else {
            if (Tool.isNotBlank(data.get("sortField")) && dataField.getFieldName().equals(data.get("sortField"))) {
                query.addSortField(dataField.getFieldName(), (String) data.get("sortType"), 0);
            }
        }
    }

    private static LeftJoinQuery getDictLeftJoinQuery(
            String sourceAlias,
            QueryField queryField,
            DataFieldBO dataField,
            Map<String, Object> data) {
        LeftJoinQuery leftJoinQuery = new LeftJoinQuery();
        leftJoinQuery.setAlias("as_" + dataField.getId());
        leftJoinQuery.setSourceAlias(sourceAlias);
        leftJoinQuery.setSourceFieldName(dataField.getFieldName());
        leftJoinQuery.setTargetId("sys_dictionary_data");
        leftJoinQuery.setTargetTableName("sys_dictionary_data");
        leftJoinQuery.setTargetPrimaryKey("dict_key");
        leftJoinQuery.addFieldMapping("dict_value", queryField.getTargetName());
        leftJoinQuery.addOnCondition("dict_id", "字符", Condition.MATCH_MODE_EQU, dataField.getRelevanceDict());
        if (Tool.isNotBlank(dataField.getNativeFieldName())) {
            leftJoinQuery.addOnCondition("dict_parent", "字段", Condition.MATCH_MODE_EQU, dataField.getNativeFieldName());
        }
        if (Tool.isNotBlank(data.get("sortField"))
                && (queryField.getOriginName().equals(data.get("sortField"))
                    || queryField.getTargetName().equals(data.get("sortField")))) {
            leftJoinQuery.setSortField("ordinal");
            leftJoinQuery.setSortType((String) data.get("sortType"));
        }
        return leftJoinQuery;
    }

    private static LeftJoinQuery getOrganizationLeftJoinQuery(
            String sourceAlias,
            QueryField queryField,
            DataFieldBO dataField,
            Map<String, Object> data) {
        LeftJoinQuery leftJoinQuery = new LeftJoinQuery();
        leftJoinQuery.setAlias("as_" + dataField.getId());
        leftJoinQuery.setSourceAlias(sourceAlias);
        leftJoinQuery.setSourceFieldName(dataField.getFieldName());
        leftJoinQuery.setTargetId("sys_organization");
        leftJoinQuery.setTargetTableName("sys_organization");
        leftJoinQuery.setTargetPrimaryKey("id");
        leftJoinQuery.addFieldMapping("name", queryField.getTargetName());
        if (Tool.isNotBlank(data.get("sortField"))
                && (queryField.getOriginName().equals(data.get("sortField"))
                || queryField.getTargetName().equals(data.get("sortField")))) {
            leftJoinQuery.setSortField("name");
            leftJoinQuery.setSortType((String) data.get("sortType"));
        }
        return leftJoinQuery;
    }

    private static LeftJoinQuery getEmployeeLeftJoinQuery(
            String sourceAlias,
            QueryField queryField,
            DataFieldBO dataField,
            Map<String, Object> data) {
        LeftJoinQuery leftJoinQuery = new LeftJoinQuery();
        leftJoinQuery.setAlias("as_" + dataField.getId());
        leftJoinQuery.setSourceAlias(sourceAlias);
        leftJoinQuery.setSourceFieldName(dataField.getFieldName());
        leftJoinQuery.setTargetId("sys_employee");
        leftJoinQuery.setTargetTableName("sys_employee");
        leftJoinQuery.setTargetPrimaryKey("id");
        leftJoinQuery.addFieldMapping("name", queryField.getTargetName());
        if (Tool.isNotBlank(data.get("sortField"))
                && (queryField.getOriginName().equals(data.get("sortField"))
                    || queryField.getTargetName().equals(data.get("sortField")))) {
            leftJoinQuery.setSortField("name");
            leftJoinQuery.setSortType((String) data.get("sortType"));
        }
        return leftJoinQuery;
    }

    private void buildDataFilter(
            Query query,
            DataModelBO dataModel,
            Map<String, Object> data) {
        if (data.get("filterList") == null) return;

        Object filterList = data.get("filterList");
        if (filterList == null) return;
        if (filterList instanceof List) {
            ((List<?>) filterList).forEach(filter -> {
                if (filter instanceof Map) {
                    ((Map<?, ?>) filter).forEach((key, value) -> dataModel.getFieldList().stream()
                            .filter(field -> field.getId().equals(key) && Tool.isNotBlank(value))
                            .findFirst()
                            .ifPresent(field ->
                                    query.addCondition(new ArrayList<>() {{
                                        add(new Condition(field.getFieldName(), field.getFieldType(), Condition.MATCH_MODE_EQU, value));
                                    }})
                            )
                    );
                }
            });
        }
    }

    private void buildPageFilter(
            Query query,
            DataModelBO dataModel,
            List<PageCompFilterBO> filterList,
            Map<String, Object> data) {
        if (filterList == null) return;

        filterList.stream()
                .filter(item -> data.containsKey(item.getId()) && Tool.isNotBlank(item.getFieldIds()))
                .forEach(item -> {
                    List<Condition> conditionList = new ArrayList<>();
                    for (String fieldId : item.getFieldIds().split(",")) {
                        dataModel.getFieldList().stream()
                                .filter(field -> field.getId().equals(fieldId) && Tool.isNotBlank(data.get(item.getId())))
                                .findFirst()
                                .ifPresent(field -> {
                                    if (DataFieldBO.FIELD_TYPE_RELATION.equals(field.getFieldType())) {
                                        Object matchValue = parseValue(field, data.get(item.getId()), item.getQueryType());
                                        Condition condition = new Condition(null, null, item.getQueryType(), matchValue);
                                        condition.setConnectSymbol("or");
                                        condition.setAliasName("as_" + field.getId());
                                        if (Tool.isNotBlank(field.getRelevanceType())
                                                && field.getRelevanceType().startsWith("字典")) {
                                            condition.setFieldName("dict_key");
                                            condition.setFieldType("字符");
                                        } else if (DataFieldBO.RELEVANCE_TYPE_UNIT.equals(field.getRelevanceType())
                                                || DataFieldBO.RELEVANCE_TYPE_DEPT.equals(field.getRelevanceType())
                                                || DataFieldBO.RELEVANCE_TYPE_EMP.equals(field.getRelevanceType())) {
                                            condition.setFieldName("id");
                                            condition.setFieldType("字符");
                                        } else if (!field.getRelevanceList().isEmpty()) {
                                            DataFieldRelevanceBO relevance = field.getRelevanceList().getLast();
                                            if (relevance == null) return;

                                            List<DataFieldBO> fieldList = dataFieldService.queryListBy(relevance.getDataModelId());
                                            if (Condition.MATCH_MODE_EQU.equals(item.getQueryType())) {
                                                fieldList.stream()
                                                        .filter(fieldItem -> fieldItem.getId().equals(relevance.getNodeFieldId()))
                                                        .findFirst()
                                                        .ifPresent(fieldItem -> {
                                                            condition.setFieldName(fieldItem.getFieldName());
                                                            condition.setFieldType(fieldItem.getFieldType());
                                                        });
                                            } else {
                                                fieldList.stream()
                                                        .filter(fieldItem -> fieldItem.getId().equals(relevance.getShowFieldId()))
                                                        .findFirst()
                                                        .ifPresent(fieldItem -> {
                                                            condition.setFieldName(fieldItem.getFieldName());
                                                            condition.setFieldType(fieldItem.getFieldType());
                                                        });
                                            }
                                        }
                                        conditionList.add(condition);
                                    } else if (DataFieldBO.FIELD_TYPE_DERIVE.equals(field.getFieldType())) {
                                        DataFieldBO dataField = dataFieldService.queryBy(field.getSourceFieldId());
                                        if (dataField == null) return;

                                        Condition condition = new Condition(
                                                dataField.getFieldName(),
                                                dataField.getFieldType(),
                                                item.getQueryType(),
                                                parseValue(field, data.get(item.getId()), item.getQueryType()));
                                        condition.setConnectSymbol("or");
                                        condition.setAliasName("as_" + field.getNativeFieldId());
                                        conditionList.add(condition);
                                    } else {
                                        Condition condition = new Condition(
                                                field.getFieldName(),
                                                field.getFieldType(),
                                                item.getQueryType(),
                                                parseValue(field, data.get(item.getId()), item.getQueryType()));
                                        condition.setConnectSymbol("or");
                                        conditionList.add(condition);
                                    }
                                });
                    }
                    if (conditionList.size() == 1) {
                        query.addCondition(conditionList);
                    } else if (conditionList.size() > 1) {
                        query.addOrCondition(conditionList);
                    }
                });
    }

    private void buildPrivilegeFilter(Query query, DataModelBO dataModel, List<PrivilegeBO> privilegeList) {
        if (privilegeList == null) return;

        List<RoleBO> roleList = Constants.getCurrentUser().getRoleList();
        for (PrivilegeBO item : privilegeList) {
            if (Tool.isBlank(item.getRoleId()) || "all".equalsIgnoreCase(item.getRoleId())) {
                query.addCondition(resolveCondition(item, dataModel));
            } else {
                for (RoleBO roleBO : roleList) {
                    if (roleBO.getId().equals(item.getRoleId())) {
                        query.addCondition(resolveCondition(item, dataModel));
                    }
                }
            }
        }
    }

    private List<Condition> resolveCondition(PrivilegeBO privilege, DataModelBO dataModel) {
        List<Condition> conditionList = new ArrayList<>();
        if (privilege == null) return conditionList;

        privilege.getConditionList().forEach(item -> dataModel.getFieldList().stream()
                .filter(field -> field.getId().equals(item.getFieldId()))
                .findFirst()
                .ifPresent(dataField -> {
                    String resultValue = SymbolUtil.parse(item.getCompareValue());
                    Condition condition = new Condition(
                            item.getConnectSymbol(),
                            item.getFrontBracket(),
                            dataField.getFieldName(),
                            dataField.getFieldType(),
                            item.getCompareSymbol(),
                            parseValue(dataField, resultValue, item.getCompareSymbol()),
                            item.getBehindBracket(),
                            item.getOrdinal() == null ? 0 : item.getOrdinal());
                    conditionList.add(condition);
                }));
        return conditionList;
    }

    @SuppressWarnings("unchecked")
    private void buildConfigFilter(Query query, DataModelBO dataModel, Map<String, Object> data) {
        if (!data.containsKey("filterList")) return;

        List<Map<String, Object>> filterList = (List<Map<String, Object>>) data.get("filterList");
        if (filterList == null || filterList.isEmpty()) return;

        List<Condition> conditionList = new ArrayList<>();
        filterList.forEach(item -> dataModel.getFieldList().stream()
                .filter(field -> field.getId().equals(item.get("fieldId")))
                .findFirst()
                .ifPresent(dataField -> {
                    String resultValue;
                    if (item.containsKey("manually") && (boolean) item.get("manually")) {
                        resultValue = SymbolUtil.parse(getString(item.get("compareValue")));
                    } else {
                        resultValue = getString(data.get(dataField.getId()));
                    }

                    Condition condition = new Condition(
                            getString(item.get("connectSymbol")),
                            getString(item.get("frontBracket")),
                            dataField.getFieldName(),
                            dataField.getFieldType(),
                            getString(item.get("compareSymbol")),
                            parseValue(dataField, resultValue, getString(item.get("compareSymbol"))),
                            getString(item.get("behindBracket")),
                            item.get("ordinal") == null ? 0 : Integer.parseInt(item.get("ordinal").toString()));
                    conditionList.add(condition);
                }));
        if (!conditionList.isEmpty()) {
            query.addCondition(conditionList);
        }
    }

    private String getString(Object value) {
        if (value == null) return null;
        return value.toString();
    }

    @SuppressWarnings("unchecked")
    private void buildDataOrder(Query query, Map<String, Object> data) {
        if (!data.containsKey("ordinalList")) return;
        List<Map<String, Object>> ordinalList = (List<Map<String, Object>>) data.get("ordinalList");
        if (ordinalList == null || ordinalList.isEmpty()) return;

        for (int i=0; i< ordinalList.size(); i++) {
            Map<String, Object> item = ordinalList.get(i);
            if (Tool.isBlank(item.get("fieldId"))) return;

            DataFieldBO dataField = dataFieldService.queryBy(item.get("fieldId").toString());
            if (dataField == null) return;

            String ordinalModel = Constants.ORDER_BY_DESC.equals(item.get("ordinalMode")) ? "desc" :
                    (Constants.ORDER_BY_ASC.equals(item.get("ordinalMode")) ? "asc" : getString(item.get("ordinalMode")));
            if (DataFieldBO.FIELD_TYPE_DERIVE.equals(dataField.getFieldType())) {
                DataFieldBO sourceField = dataFieldService.queryBy(dataField.getSourceFieldId());
                query.addSortField(
                        "as_" + dataField.getNativeFieldId(),
                        sourceField.getFieldName(),
                        ordinalModel,
                        i);
            } else {
                query.addSortField(dataField.getFieldName(), ordinalModel, i);
            }
        }
    }

    private void buildConfigOrder(Query query, List<DataTableOrdinalBO> ordinalList) {
        if (!query.getSortFieldList().isEmpty() || ordinalList == null) return;

        ordinalList.forEach(item -> {
            if (Tool.isBlank(item.getFieldId())) return;

            DataFieldBO dataField = dataFieldService.queryBy(item.getFieldId());
            if (dataField == null) return;

            String ordinalModel = Constants.ORDER_BY_DESC.equals(item.getOrdinalMode()) ? "desc" :
                    (Constants.ORDER_BY_ASC.equals(item.getOrdinalMode()) ? "asc" : item.getOrdinalMode());
            if (DataFieldBO.FIELD_TYPE_DERIVE.equals(dataField.getFieldType())) {
                DataFieldBO sourceField = dataFieldService.queryBy(dataField.getSourceFieldId());
                query.addSortField(
                        "as_" + dataField.getNativeFieldId(),
                        sourceField.getFieldName(),
                        ordinalModel,
                        item.getOrdinal());
            } else if (DataFieldBO.FIELD_TYPE_RELATION.equals(dataField.getFieldType())) {
                query.addSortField(
                        "as_" + dataField.getId(),
                        getRelationFieldName(dataField),
                        ordinalModel,
                        item.getOrdinal());
            } else {
                query.addSortField(dataField.getFieldName(), ordinalModel, item.getOrdinal());
            }
        });
    }

    private String getRelationFieldName(DataFieldBO field) {
        if (DataFieldBO.RELEVANCE_TYPE_MODEL.equals(field.getRelevanceType())) {
            if (field.getRelevanceList() != null && !field.getRelevanceList().isEmpty()) {
                DataFieldRelevanceBO relevance = field.getRelevanceList().getLast();
                return relevance.getShowFieldName();
            }
        } else if (DataFieldBO.RELEVANCE_TYPE_AREA.equals(field.getRelevanceType())
                || DataFieldBO.RELEVANCE_TYPE_UNIT.equals(field.getRelevanceType())
                || DataFieldBO.RELEVANCE_TYPE_ENP.equals(field.getRelevanceType())
                || DataFieldBO.RELEVANCE_TYPE_DEPT.equals(field.getRelevanceType())
                || DataFieldBO.RELEVANCE_TYPE_EMP.equals(field.getRelevanceType())) {
            return "name";
        } else if (field.getRelevanceType().contains(DataFieldBO.RELEVANCE_TYPE_DICT)) {
            return "ordinal";
        }
        return null;
    }

    private void buildDefaultOrder(Query query, List<DataFieldBO> fieldList) {
        if (!query.getSortFieldList().isEmpty() || fieldList.isEmpty()) return;
        if (fieldList.stream().anyMatch(field -> field.getFieldName().equalsIgnoreCase("id"))) {
            query.addSortField("id", "desc", 1);
        } else if (fieldList.stream().anyMatch(field -> field.getFieldName().equalsIgnoreCase("create_time"))) {
            query.addSortField("create_time", "desc", 1);
        }
    }

    private Object parseValue(DataFieldBO field, Object value, String matchValue) {
        if (Tool.isBlank(value)) return null;
        if (Condition.MATCH_MODE_IN.equals(matchValue)) return value;

        // 字符、整数、小数、日期、时间、图片、视频、附件、大文本
        if (DataFieldBO.FIELD_TYPE_INTEGER.equals(field.getFieldType())) {
            return Integer.parseInt(value.toString());
        } else if (DataFieldBO.FIELD_TYPE_NUMERIC.equals(field.getFieldType())) {
            return Double.parseDouble(value.toString());
        } else if (DataFieldBO.FIELD_TYPE_DATETIME.equals(field.getFieldType())) {
            try {
                if (value.toString().matches("\\d+")) {
                    return Long.parseLong(value.toString());
                } else if (value.toString().matches("\\d{4}-\\d{2}-\\d{2}")) {
                    long time = Objects.requireNonNull(DateUtil.parseDate(value.toString(), "yyyy-MM-dd")).getTime();
                    if (Tool.isNotBlank(matchValue)) {
                        if (matchValue.equals("小于等于")) {
                            return time + 24 * 60 * 60 * 1000 - 1;
                        } else if (matchValue.equals("小于")) {
                            return time + 24 * 60 * 60 * 1000;
                        } else {
                            return time;
                        }
                    } else {
                        return time;
                    }
                } else {
                    throw new ParseException("日期不正确！", 0);
                }
            } catch (ParseException e) {
                throw new RuntimeException(e.getMessage(), e.getCause());
            }
        } else if (DataFieldBO.RELEVANCE_TYPE_EMP.equals(field.getRelevanceType())) {
            return value.toString().contains("@") ? value.toString().split("@")[1] : value;
        }
        return value;
    }

    public static void main(String[] args) {
        System.out.println("2025-01-02".matches("\\d{4}-\\d{2}-\\d{2}"));
    }
}
